package org.computate.model.dao;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.computate.model.item.TransitDay;

import com.google.inject.Inject;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.NotFoundException;
import com.googlecode.objectify.ObjectifyOpts;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;
import com.googlecode.objectify.util.DAOBase;


public class TransitDayDaoImpl extends DAOBase implements TransitDayDao {
	
	@Inject private Daos daos;
	
	public TransitDayDaoImpl() {
		super(new ObjectifyOpts().setSessionCache(true));
	}
	
	static {
        ObjectifyService.register(TransitDay.class);
    }
	
	public TransitDay create() {
		TransitDay result = new TransitDay();
		
		if(!result.isPopulated()) {
			result.addFields();
			result.setPopulated(true);
		}
		ofy().put(result);
		
		return result;
	}
	
	public TransitDay put(TransitDay item) {
		ofy().put(item);
		
		return item;
	}
	
	public TransitDay save(Object itemObject) {
		TransitDay result = null;
		
		if(itemObject instanceof TransitDay) {
			result = (TransitDay)itemObject;
			
			ofy().put(result);
			result.addFields();
			result.setPopulated(true);
		}
		
		return result;
	}
	
	public TransitDay create(String name) {
		TransitDay result = new TransitDay();
		
		if(!result.isPopulated()) {
			result.addFields();
			result.setPopulated(true);
		}
		if(!StringUtils.isEmpty(name))
			result.setName(name);
		ofy().put(result);
		
		return result;
	}
	
	public TransitDay create(String name, String parentField, Long parentId, int getLevels) {
		TransitDay result = new TransitDay();
		
		if(!result.isPopulated()) {
			result.addFields();
			result.setPopulated(true);
		}
		if(!StringUtils.isEmpty(name))
			result.setName(name);
		if(!StringUtils.isEmpty(parentField) && parentId != null) {
			try {
				PropertyDescriptor propertyDescriptor = new PropertyDescriptor(parentField, TransitDay.class);
				Method setter = propertyDescriptor.getWriteMethod();
				Key<TransitDay> key = new Key<TransitDay>(TransitDay.class, parentId);
				
				setter.invoke(result, key);
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IntrospectionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		ofy().put(result);
		result.addItems(getLevels - 1, daos);
		
		return result;
	}
	
	public TransitDay get(Long id, int getLevels) {
		TransitDay result = null;
		
		if(id != null && getLevels > 0) {
			result = ofy().get(TransitDay.class, id);
		}
		if(result != null && !result.isPopulated()) {
			result.addFields();
			result.addItems(getLevels - 1, daos);
			result.setPopulated(true);
		}
		
		return result;
	}
	
	public TransitDay get(String name, int getLevels) {
		TransitDay result = ofy().query(TransitDay.class).filter("name", name).get();
		
		if(result != null && getLevels > 0 && !result.isPopulated()) {
			result.addFields();
			result.addItems(getLevels - 1, daos);
			result.setPopulated(true);
		}
		
		return result;
	}
	
	public TransitDay delete(Long id) {
		TransitDay result = ofy().get(TransitDay.class, id);
		
		ofy().delete(result);
		
		return result;
	}
	
	public TransitDay delete(TransitDay item) {
		TransitDay result = null;
		
		if(item != null) {
			result = ofy().get(TransitDay.class, item.getId());
			ofy().delete(result);
		}
		
		return result;
	}
	
	public List<TransitDay> list(int listLevels) {
		List<Key<TransitDay>> keys = ofy().query(TransitDay.class).listKeys();
		List<TransitDay> results = new ArrayList<TransitDay>();
		
		if(listLevels > 0) {
			for(Key<TransitDay> key : keys) {
				try {
					TransitDay result = ofy().get(TransitDay.class, key.getId());
					
					if(result != null && !result.isPopulated()) {
						result.addFields();
						result.addItems(listLevels - 1, daos);
						result.setPopulated(true);
					}
					results.add(result);
				} catch (NotFoundException e) {
					// ignore because the TransitDay with the given id was recently deleted
				}
			}
		}
		
		return results;
	}
	
	public List<TransitDay> list(Query<TransitDay> query, int listLevels) {
		List<TransitDay> results = new ArrayList<TransitDay>();
		
		if(query != null) {
			results = query.list();
		}
		for(TransitDay result : results) {
			if(!result.isPopulated()) {
				result.addFields();
				result.addItems(listLevels - 1, daos);
				result.setPopulated(true);
			}
		}
		
		return results;
	}
}
